package hydrap2p.upload;

import hydrap2p.ServiceLocation;
import hydrap2p.logging.Level;

import java.util.LinkedList;
import java.util.List;

public class UploadListeners {
	private List<UploadListenerIface> listeners;
	private UploadQueue queue;
	
	public UploadListeners()
	{
		listeners=new LinkedList<UploadListenerIface>();
	}
	
	public void setUploadQueue(UploadQueue queue)
	{
		this.queue=queue;
	}
	
	public void subscribeListener(UploadListenerIface listener)
	{
		synchronized(listeners)
		{
			listeners.add(listener);
		}
		
		if (queue!=null)
		{
			queue.syncListener(listener);
		}
	}
	public boolean unsubscribeListener(UploadListenerIface listener)
	{
		synchronized(listeners)
		{
			return listeners.remove(listener);
		}
	}
	public void unsubscribeListener(ServiceLocation location)
	{
		synchronized(listeners)
		{
			for (UploadListenerIface listener:listeners)
			{
				if (listener instanceof UploadListenerThrift)
				{
					UploadListenerThrift thrifter=(UploadListenerThrift) listener;
					if (thrifter.getLocation().equals(location))
					{
						listeners.remove(listener);
						break;
					}
				}
			}
		}
	}

	public void newUpload(UploadQueued upload) {
		List<UploadListenerIface> mylisteners;
		List<UploadListenerIface> failedlisteners=new LinkedList<UploadListenerIface>();
		synchronized(listeners)
		{
			mylisteners=new LinkedList<UploadListenerIface>(listeners);
		}
		
		for (UploadListenerIface listener : mylisteners)
		{
			try {
				listener.newUpload(upload);
			} catch (Exception e) {
				UploadLogging.log(Level.ERROR, "Upload - Listeners", "Failed to notify an upload listener about a new upload: "+e.getLocalizedMessage());
				failedlisteners.add(listener);
			}
		}

		for (UploadListenerIface listener : failedlisteners)
		{
			unsubscribeListener(listener);
		}
	}

	public void removedUpload(UploadQueued upload) {
		List<UploadListenerIface> mylisteners;
		List<UploadListenerIface> failedlisteners=new LinkedList<UploadListenerIface>();
		synchronized(listeners)
		{
			mylisteners=new LinkedList<UploadListenerIface>(listeners);
		}
		
		for (UploadListenerIface listener : mylisteners)
		{
			try {
				listener.removedUpload(upload);
			} catch (Exception e) {
				UploadLogging.log(Level.ERROR, "Upload - Listeners", "Failed to notify an upload listener about a removed upload: "+e.getLocalizedMessage());
				failedlisteners.add(listener);
			}
		}

		for (UploadListenerIface listener : failedlisteners)
		{
			unsubscribeListener(listener);
		}
	}

	public void updateUpload(UploadQueued upload) {
		List<UploadListenerIface> mylisteners;
		List<UploadListenerIface> failedlisteners=new LinkedList<UploadListenerIface>();
		synchronized(listeners)
		{
			mylisteners=new LinkedList<UploadListenerIface>(listeners);
		}
		
		for (UploadListenerIface listener : mylisteners)
		{
			try {
				listener.updateUpload(upload);
			} catch (Exception e) {
				UploadLogging.log(Level.ERROR, "Upload - Listeners", "Failed to notify an upload listener about an updated upload: "+e.getLocalizedMessage());
				failedlisteners.add(listener);
			}
		}

		for (UploadListenerIface listener : failedlisteners)
		{
			unsubscribeListener(listener);
		}
	}
}
